package r25.board;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import r25.engine.Composition;
import r25.engine.IGameService;
import r25.room.IRoom;
import r25.room.IRoom.INITIAL_RANDOM_SET;

public class Board5x5 extends AbstractBoard {
	public final int LOWER_LIMIT_X = -2;
	public final int UPPER_LIMIT_X = 2;
	public final int LOWER_LIMIT_Y = -2;
	public final int UPPER_LIMIT_Y = 2;
	public final int SIZE_X = 1 + UPPER_LIMIT_X - LOWER_LIMIT_X;
	public final int SIZE_Y = 1 + UPPER_LIMIT_Y - LOWER_LIMIT_Y;

	public Board5x5() {
		board = new IRoom[SIZE_X][SIZE_Y];
	}

	@Override
	public void setup(IGameService gs, Composition comp) throws Exception {
		if (SIZE_X * SIZE_Y != comp.countCompositionSize())
			throw new Exception("Invalid composition size: " + comp);

		List<IRoom> cornerRooms = new ArrayList<IRoom>();
		List<IRoom> closeRooms = new ArrayList<IRoom>();
		List<IRoom> bufferRooms = new ArrayList<IRoom>();
		IRoom instance = null;

		Map<String, Integer> compositionRooms = comp.getComposition();
		for (Entry<String, Integer> e : compositionRooms.entrySet()) {
			for (int i = 0; i < e.getValue(); i++) {
				instance = gs.getRoomInstance(e.getKey());
				if (INITIAL_RANDOM_SET.CENTRAL.equals(instance
						.getInitialRandomSet())) {
					// more than 1 CENTRAL room should return an Exception
					addRoom(instance);
				} else if (INITIAL_RANDOM_SET.CLOSE.equals(instance
						.getInitialRandomSet())) {
					closeRooms.add(instance);
				} else if (INITIAL_RANDOM_SET.CORNER.equals(instance
						.getInitialRandomSet())) {
					cornerRooms.add(instance);
				} else {
					bufferRooms.add(instance);
				}
			}
		}

		// complete cornerRooms with bufferRooms
		while (cornerRooms.size() < 12) {
			cornerRooms.add(gs.pickRandomRoom(bufferRooms));
		}
		// put remaining bufferRooms in closeRooms
		closeRooms.addAll(bufferRooms);

		// allocate corners with cornerRooms[]
		// allocate close rooms with closeRooms[]
		for (int y = UPPER_LIMIT_Y; y >= LOWER_LIMIT_Y; y--) {
			for (int x = LOWER_LIMIT_X; x <= UPPER_LIMIT_X; x++) {
				if ((x == 0) && (y == 0))
					continue;
				if (((x != 0) && ((y == UPPER_LIMIT_Y) || (y == LOWER_LIMIT_Y)))
						|| ((Math.abs(y) == 1) && ((x == UPPER_LIMIT_X) || (x == LOWER_LIMIT_X)))) {
					instance = gs.pickRandomRoom(cornerRooms);
				} else {
					instance = gs.pickRandomRoom(closeRooms);
				}
				instance.setPosX(x);
				instance.setPosY(y);
				addRoom(instance);
			}
		}

	}

	@Override
	public int getLowerLimitX() {
		return LOWER_LIMIT_X;
	}

	@Override
	public int getUpperLimitX() {
		return UPPER_LIMIT_X;
	}

	@Override
	public int getLowerLimitY() {
		return LOWER_LIMIT_Y;
	}

	@Override
	public int getUpperLimitY() {
		return UPPER_LIMIT_Y;
	}

	@Override
	public int getSizeX() {
		return SIZE_Y;
	}

	@Override
	public int getSizeY() {
		return SIZE_Y;
	}
}
